home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr48 / btv115.zip / BTVTYPE.PAS < prev    next >
Pascal/Delphi Source File  |  1993-04-01  |  23KB  |  894 lines

  1. {*
  2. * ┌───────────────────────────────────────────────────────────────┐
  3. * │ BTVTYPE.PAS  Version 1.0                                      │
  4. * │                                                               │
  5. * │ BTRIEVE data type conversion routines for Turbo Pascal 6.0.   │
  6. * │                                                               │
  7. * │ Copyright (c) 1992 by Richard W. Hansen, all rights reserved. │
  8. * └───────────────────────────────────────────────────────────────┘
  9. *
  10. *
  11. *  Requires Turbo Pascal version 6.0
  12. *
  13. *
  14. *  Registration and payment of a license fee is required for any use, whether
  15. *  in whole or part, of this source code.
  16. *
  17. *}
  18.  
  19. {****************************************************************************}
  20. {*   REVISION HISTORY                                                       *}
  21. {*                                                                          *}
  22. {*  Date     Who  What                                                      *}
  23. {* ======================================================================== *}
  24. {* 06/05/92  RWH  First version.                                            *}
  25. {****************************************************************************}
  26.  
  27. UNIT BTVType;
  28. {$F-}
  29. {$X+}
  30. {$A-}
  31. {$V-}
  32.  
  33.  
  34. INTERFACE
  35.  
  36.  
  37. TYPE
  38.   BDateRec  = record
  39.     Month : Byte;
  40.     Day   : Byte;
  41.     Year  : Word;
  42.   end;
  43.  
  44.  
  45.   BTimeRec  = record
  46.     Hundred : Byte;
  47.     Second  : Byte;
  48.     Minute  : Byte;
  49.     Hour    : Byte;
  50.   end;
  51.  
  52.  
  53. {
  54.   This Unit includes routines to convert Btrieve data types to and from
  55.   Pascal strings. Also included are routines for converting the BFloat types
  56.   to Turbo Pascal Singles, and Doubles.
  57.  
  58.   These routines are intended to ease the use of the Btrieve data types.
  59.   At first, some of them may seem redundant or of little use. They are
  60.   designed primarily for use with raw data from Btrieve records. All the
  61.   routines use untyped VAR parameters to handle the Btrieve types that are
  62.   not defined in Pascal. Untyped VAR parameters get around Pascal's strict
  63.   type checking, so you should exercise a bit more care calling these
  64.   routines.
  65.  
  66.   A typical call to convert IEEE single to a string might be:
  67.  
  68.     St := FloatToStr(Buffer[10], 4, 10, 4);
  69.  
  70.   Notice how the untyped parameter lets you convert data from any part of a
  71.   record buffer (though you could just as well have passed a variable of
  72.   type single in this example). Most of the routines have a size parameter,
  73.   in the example above it is the second parameter (4). The 4 indicates that
  74.   we want to convert a 4 byte Single into a string.
  75.  
  76.   It is very important that you pass the correct size. The size always refers
  77.   to the size of the Btrieve type and controls the type conversion (say to
  78.   single or double) or the size of resulting data when converting from a
  79.   string to a Btrieve type. If you specify the size incorrectly, you will
  80.   get garbage results or overwrite other data in memory.
  81.  
  82.   There are a couple of conversion routines left out, string to time and
  83.   string to date, and string to logical. The time and date did not seem
  84.   worth the effort, given the variety of possible inputs.
  85.  
  86.   As a final note, if you use any of the routines for IEEE single or double
  87.   types you will need to compile your program with the $N+ and $E+ compiler
  88.   directives.
  89. }
  90.  
  91.  
  92. {* String to Data conversion routines *}
  93.  
  94. Function StrToInteger(    S    : String;
  95.                       var Int;
  96.                           Size : Byte): Boolean;
  97.  
  98. Function StrToUnsigned(    S    : String;
  99.                        var Int;
  100.                            Size : Byte): Boolean;
  101.  
  102. Procedure StrToLString(    S : String;
  103.                        var Str);
  104.  
  105. Procedure StrToZString(    S : String;
  106.                        var Str);
  107.  
  108. Function StrToFloat(    S    : String;
  109.                     var Float;
  110.                         Size : Byte): Boolean;
  111.  
  112. Procedure StrToString(    S : String;
  113.                       var Str);
  114.  
  115. Function StrToBFloat(    S    : String;
  116.                      var BFloat;
  117.                          Size : Byte): Boolean;
  118.  
  119. Procedure StrToNumeric(    S    : String;
  120.                        var Numeric;
  121.                            Size : Byte);
  122.  
  123. Function StrToDecimal(    S    : String;
  124.                       var Decimal;
  125.                           Size : Byte): Boolean;
  126.   { The sign, negatives only, must be in first position, i.e. -1111.00
  127.     Make sure the decimal is big enough to hold the converted string!!!
  128.   }
  129.  
  130.  
  131.  
  132. {* Data to string conversion routines *}
  133.  
  134. Function LogicalToStr(var Logical;
  135.                           Size  : Byte): String;
  136.  
  137. Function IntegerToStr(var Int;
  138.                           Size : Byte;
  139.                           Width: Byte): String;
  140.  
  141. Function UnsignedToStr(var Int;
  142.                            Size : Byte;
  143.                            Width: Byte): String;
  144.  
  145. Function LStringToStr(var Str): String;
  146.  
  147. Function ZStringToStr(var Str): String;
  148.  
  149. Function TimeToStr(var Time): String;
  150.  
  151. Function DateToStr(var Date): String;
  152.  
  153. Function FloatToStr(var Float;
  154.                         Size    : Byte;
  155.                         Width   : Byte;
  156.                         Decimals: Byte): String;
  157.  
  158. Function StringToStr(var Str;
  159.                          Size : Byte): String;
  160.  
  161. Function DecimalToStr(var Decimal;
  162.                           Size : Byte): String;
  163.  
  164. Function BFloatToStr(var BFloat;
  165.                          Size    : Byte;
  166.                          Width   : Byte;
  167.                          Decimals: Byte): String;
  168.  
  169. Function NumericToStr(var Numeric;
  170.                           Size   : Byte): String;
  171.  
  172.  
  173.  
  174. {* BFloat conversion routines *}
  175.  
  176. Function BFloatToSingle(var BFloat): Single;
  177.   {- MS Single Precision (4 Byte) Float to TP IEEE Single }
  178.  
  179. Procedure SingleToBFloat(var BFloat;
  180.                              Sgl   : Single);
  181.   {- TP IEEE Single to MS Single Precision (4 Byte) Float }
  182.  
  183.  
  184. Function BFloatToDouble(var BFloat): Double;
  185.   {- MS Double precision (8 Byte) to TP IEEE Double }
  186.  
  187. Procedure DoubleToBFloat(var BFloat;
  188.                              Dbl   : Double);
  189.   {- TP IEEE Double to MS Double Precision (8 Byte) Float }
  190.  
  191.  
  192.  
  193. CONST
  194.   DecimalPt : Char  = '.';
  195.  
  196. {============================================================================}
  197. IMPLEMENTATION
  198.  
  199.  
  200. TYPE
  201.   Chars = Array[1..256] of Char;
  202.   Bytes = Array[1..256] of Byte;
  203.  
  204.  
  205. {--- BFloat Routines ---}
  206.  
  207. {***************************************************************************}
  208. { Turbo Pascal IEEE Single                                                  }
  209. {                                                                           }
  210. { Byte  4      43        32      21      1                                  }
  211. {  Bit  7 65432107 65432107654321076543210                                  }
  212. {      +-+--------+----------------------+                                  }
  213. {      |S| 8 bit  |                      |                                  }
  214. {      |I|exponent| 23 bit mantissa      |                                  }
  215. {      |G|        |                      |                                  }
  216. {      |N|        |                      |                                  }
  217. {      +-+--------+----------------------+                                  }
  218. {***************************************************************************}
  219. { Microsoft Basic Single Precsion and Btrieve 4 Byte BFLOAT                 }
  220. {                                                                           }
  221. { Byte  4      4 3       32      21      1                                  }
  222. {  Bit  76543210 7 65432107654321076543210                                  }
  223. {      +--------+-+----------------------+                                  }
  224. {      | 8 bit  |S|                      |                                  }
  225. {      |exponent|I| 23 bit mantissa      |                                  }
  226. {      |        |G|                      |                                  }
  227. {      |        |N|                      |                                  }
  228. {      +--------+-+----------------------+                                  }
  229. {***************************************************************************}
  230.  
  231. Function BFloatToSingle(var BFloat): Single;
  232.  
  233.   var
  234.     Sign     : Byte;
  235.     Exponent : Byte;
  236.     Sgl      : Single;
  237.     Byt      : Bytes Absolute Sgl;
  238.  
  239.   begin
  240.     Sgl := Single(BFloat);
  241.     Exponent := Byt[4];
  242.  
  243.     if (Exponent <> 0) then
  244.     begin
  245.       Sign := Byt[3] AND $80;
  246.       { adjust the exponent bias }
  247.       Exponent := Exponent - $81 + $7F;
  248.       { reassemble  }
  249.       Byt[4] := Sign OR (Exponent SHR 1);
  250.       Byt[3] := Byt[3] OR (Exponent SHL 7);
  251.     end;
  252.  
  253.     BFloatToSingle := Sgl;
  254.   end;
  255.  
  256. Procedure SingleToBFloat(var BFloat;
  257.                              Sgl : Single);
  258.  
  259.   var
  260.     Sign     : Byte;
  261.     Exponent : Byte;
  262.     Byt      : Bytes Absolute BFloat;
  263.  
  264.   begin
  265.     Single(BFloat) := Sgl;
  266.     Exponent := (Byt[4] SHL 1) OR (Byt[3] SHR 7);
  267.  
  268.     if (Exponent <> 0) then
  269.     begin
  270.       Sign := Byt[4] AND $80;
  271.       { adjust the exponent bias }
  272.       Exponent := Exponent - $7F + $81;
  273.       { reassemble  }
  274.       Byt[4]   := Exponent;
  275.       Byt[3]   := Sign OR Byt[3];
  276.     end;
  277.   end;
  278.  
  279. {***************************************************************************}
  280. { Turbo Pascal IEEE Double                                                  }
  281. {                                                                           }
  282. { byte  8 ......87... ...76......65......54......43......32......21......1  }
  283. {  bit  7 65432107654 3210765432107654321076543210765432107654321076543210  }
  284. {      +-+-----------+---------------------------------------------------+  }
  285. {      |S|           |                                                   |  }
  286. {      |I| 11 bit    | 52 bit mantissa                                   |  }
  287. {      |G| exponent  |                                                   |  }
  288. {      |N|           |                                                   |  }
  289. {      +-+-----------+---------------------------------------------------+  }
  290. {***************************************************************************}
  291. { Microsoft Basic Double Precsion and Btrieve 8 Byte BFLOAT                 }
  292. {                                                                           }
  293. { byte  8......8 7 7.....76......65......54......43......32......21......1  }
  294. {  bit  76543210 7 6543210765432107654321076543210765432107654321076543210  }
  295. {      +--------+-+------------------------------------------------------+  }
  296. {      |        |S|                                                      |  }
  297. {      |8 bit   |I| 55 bit mantissa                                      |  }
  298. {      |exponent|G|                                                      |  }
  299. {      |        |N|                                                      |  }
  300. {      +--------+-+------------------------------------------------------+  }
  301. {***************************************************************************}
  302.  
  303. Function BFloatToDouble(var BFloat): Double;
  304.  
  305.   var
  306.     Dbl      : Array[1..8] of Byte;
  307.     Exponent : Integer;
  308.     Exp      : Array[1..2] of Byte Absolute Exponent;
  309.  
  310.   begin
  311.     Exponent := BYTES(BFloat)[8];
  312.     FillChar(Dbl, 8, 0);
  313.  
  314.     if (Exponent <> 0) then
  315.     begin
  316.       { change BIAS to 1023 }
  317.       Exponent:= Exponent - 129 + 1023;
  318.       Dbl[8]  := (BYTES(BFloat)[7] AND $80) + (Exp[1] SHR 4) + (Exp[2] SHL 4);
  319.       Dbl[7]  := (Exp[1] SHL 4) + ((BYTES(BFloat)[7] and $7F) SHR 3);
  320.       Dbl[6]  := (BYTES(BFloat)[7] SHL 5) + (BYTES(BFloat)[6] SHR 3);
  321.       Dbl[5]  := (BYTES(BFloat)[6] SHL 5) + (BYTES(BFloat)[5] SHR 3);
  322.       Dbl[4]  := (BYTES(BFloat)[5] SHL 5) + (BYTES(BFloat)[4] SHR 3);
  323.       Dbl[3]  := (BYTES(BFloat)[4] SHL 5) + (BYTES(BFloat)[3] SHR 3);
  324.       Dbl[2]  := (BYTES(BFloat)[3] SHL 5) + (BYTES(BFloat)[2] SHR 3);
  325.       Dbl[1]  := (BYTES(BFloat)[2] SHL 5) + (BYTES(BFloat)[1] SHR 3);
  326.     end;
  327.  
  328.     BFloatToDouble  := Double(Dbl);
  329.   end;
  330.  
  331. Procedure DoubleToBFloat(var BFloat;
  332.                              Dbl : Double);
  333.   var
  334.     Exponent : Integer;
  335.     Byt      : Bytes Absolute Dbl;
  336.  
  337.   begin
  338.     Exponent := Byt[8] AND $7F;
  339.     Exponent := (Exponent SHL 4) + (Byt[7] shr 4);
  340.     FillChar(BYTES(BFloat), 8, 0);
  341.  
  342.     if (Exponent <> 0) then
  343.     begin
  344.       { change BIAS to 129 }
  345.       Exponent := Exponent - 1023 + 129;
  346.       BYTES(BFloat)[8] := Exponent;
  347.       BYTES(BFloat)[7] := (Byt[8] and $80) + ((Byt[7] and $0F) SHL 3) + (Byt[6] SHR 5);
  348.       BYTES(BFloat)[6] := (Byt[6] SHL 3) + (Byt[5] SHR 5);
  349.       BYTES(BFloat)[5] := (Byt[5] SHL 3) + (Byt[4] SHR 5);
  350.       BYTES(BFloat)[4] := (Byt[4] SHL 3) + (Byt[3] SHR 5);
  351.       BYTES(BFloat)[3] := (Byt[3] SHL 3) + (Byt[2] SHR 5);
  352.       BYTES(BFloat)[2] := (Byt[2] SHL 3) + (Byt[1] SHR 5);
  353.       BYTES(BFloat)[1] := (Byt[1] SHL 3);
  354.     end;
  355.   end;
  356.  
  357. Function BFloatToStr(var BFloat;
  358.                          Size    : Byte;
  359.                          Width   : Byte;
  360.                          Decimals: Byte): String;
  361.  
  362.   var
  363.     S : String;
  364.  
  365.   begin
  366.     Case Size of
  367.       4 : Str(BFloatToSingle(BFloat):Width:Decimals, S);
  368.       8 : Str(BFloatToDouble(BFloat):Width:Decimals, S);
  369.       else
  370.         S := 'ERROR';
  371.     end;
  372.  
  373.     BFloatToStr := S;
  374.   end;
  375.  
  376. Function StrToBFloat(    S    : String;
  377.                      var BFloat;
  378.                          Size : Byte): Boolean;
  379.  
  380.   var
  381.     Err : Integer;
  382.     Sgl : Single;
  383.     Dbl : Double;
  384.  
  385.   begin
  386.  
  387.     Case Size of
  388.       4 :
  389.       begin
  390.         Val(S, Sgl, Err);
  391.  
  392.         if (Err = 0) then
  393.           SingleToBFloat(BFloat, Sgl);
  394.       end;
  395.       8 :
  396.       begin
  397.         Val(S, Dbl, Err);
  398.  
  399.         if (Err = 0) then
  400.           DoubleToBFloat(BFloat, Dbl);
  401.       end;
  402.     end;
  403.  
  404.     StrToBFloat := (Err = 0);
  405.   end;
  406.  
  407.  
  408. {--- Integer Routines ---}
  409.  
  410. Function IntegerToStr(var Int;
  411.                           Size : Byte;
  412.                           Width: Byte): String;
  413.  
  414.   var
  415.     S : String[30];
  416.  
  417.   begin
  418.     Case Size of
  419.       2 : Str(INTEGER(Int):Width, S);
  420.       4 : Str(LONGINT(Int):Width, S);
  421.       else
  422.         S := 'ERROR';
  423.     end;
  424.  
  425.     IntegerToStr := S;
  426.   end;
  427.  
  428. Function StrToInteger(    S    : String;
  429.                       var Int;
  430.                           Size : Byte): Boolean;
  431.  
  432.   var
  433.     Err : Integer;
  434.  
  435.   begin
  436.     Case Size of
  437.       2 : Val(S, INTEGER(Int), Err);
  438.       4 : Val(S, LONGINT(Int), Err);
  439.     end;
  440.  
  441.     StrToInteger := (Err = 0);
  442.   end;
  443.  
  444.  
  445. {--- Unsigned Routines ---}
  446.  
  447. Function UnsignedToStr(var Int;
  448.                            Size : Byte;
  449.                            Width: Byte): String;
  450.  
  451.   var
  452.     S : String[30];
  453.  
  454.   begin
  455.     Case Size of
  456.       1 : Str(BYTE(Int):Width, S);
  457.       2 : Str(WORD(Int):Width, S);
  458.       4 : Str(LONGINT(Int):Width, S);
  459.       else
  460.         S := 'ERROR';
  461.     end;
  462.  
  463.     UnsignedToStr := S;
  464.   end;
  465.  
  466. Function StrToUnsigned(    S    : String;
  467.                        var Int;
  468.                            Size : Byte): Boolean;
  469.  
  470.   var
  471.     Err : Integer;
  472.  
  473.   begin
  474.     Case Size of
  475.       1 : Val(S, BYTE(Int), Err);
  476.       2 : Val(S, INTEGER(Int), Err);
  477.       4 : Val(S, LONGINT(Int), Err);
  478.     end;
  479.  
  480.     StrToUnsigned := (Err = 0);
  481.   end;
  482.  
  483.  
  484. {--- LString Routines ---}
  485.  
  486. Function LStringToStr(var Str): String;
  487.  
  488.   var
  489.     S : String;
  490.  
  491.   begin
  492.     Move(CHARS(Str), S[0], BYTE(Str) + 1);
  493.     LStringToStr := S;
  494.   end;
  495.  
  496. Procedure StrToLString(    S : String;
  497.                        var Str);
  498.   begin
  499.     Move(S[0], Str, BYTE(S[0]) + 1);
  500.   end;
  501.  
  502.  
  503. {--- ZString Routines ---}
  504.  
  505. Function ZStringToStr(var Str): String;
  506.  
  507.   var
  508.     i : Byte;
  509.     S : String;
  510.  
  511.   begin
  512.     i := 0;
  513.  
  514.     While (CHARS(Str)[i+1] <> #0) and (i < 255) do
  515.     begin
  516.       Inc(i);
  517.       S[i] := CHARS(Str)[i];
  518.     end;
  519.  
  520.     BYTE(S[0]) := i;
  521.     ZStringToStr := S;
  522.   end;
  523.  
  524. Procedure StrToZString(    S : String;
  525.                        var Str);
  526.   begin
  527.     Move(S[1], Str, BYTE(S[0]));
  528.     CHARS(Str)[BYTE(S[0])+1] := #0;
  529.   end;
  530.  
  531.  
  532. {--- Time Routines ---}
  533.  
  534. Function TimeToStr(var Time): String;
  535.  
  536.   var
  537.     S : String[30];
  538.     X : String[2];
  539.     i : Byte;
  540.     T : BTimeRec Absolute Time;
  541.  
  542.   begin
  543.     Str(T.Hour:2, S);
  544.     S := S + ':';
  545.     Str(T.Minute:2, X);
  546.     S := S + X + ':';
  547.     Str(T.Second:2, X);
  548.     S := S + X + ':';
  549.     Str(T.Hundred:2, X);
  550.     S := S + X;
  551.  
  552.     for i := 1 to Length(S) do
  553.       if S[i] = ' ' then
  554.         S[i] := '0';
  555.  
  556.     TimeToStr := S;
  557.   end;
  558.  
  559.  
  560. {--- Date Routines ---}
  561.  
  562. Function DateToStr(var Date): String;
  563.  
  564.   var
  565.     S : String[30];
  566.     X : String[4];
  567.     i : Byte;
  568.     D : BDateRec Absolute Date;
  569.  
  570.   begin
  571.     Str(D.Month:2, S);
  572.     S := S + '/';
  573.     Str(D.Day:2, X);
  574.     S := S + X + '/';
  575.  
  576.     if (D.Year > 100) then
  577.       Str(D.Year:4, X)
  578.     else
  579.       Str(D.Year:2, X);
  580.  
  581.     S := S + X;
  582.  
  583.     for i := 1 to Length(S) do
  584.       if S[i] = ' ' then
  585.         S[i] := '0';
  586.  
  587.     DateToStr := S;
  588.   end;
  589.  
  590.  
  591. {--- Float Routines ---}
  592.  
  593. Function FloatToStr(var Float;
  594.                         Size    : Byte;
  595.                         Width   : Byte;
  596.                         Decimals: Byte): String;
  597.  
  598.   var
  599.     S   : String;
  600.  
  601.   begin
  602.     Case Size of
  603.       4 : Str(SINGLE(Float):Width:Decimals, S);
  604.       8 : Str(DOUBLE(Float):Width:Decimals, S);
  605.       else
  606.         S := 'ERROR';
  607.     end;
  608.  
  609.     FloatToStr := S;
  610.   end;
  611.  
  612. Function StrToFloat(    S    : String;
  613.                     var Float;
  614.                         Size : Byte): Boolean;
  615.  
  616.   var
  617.     Err : Integer;
  618.  
  619.   begin
  620.     Case Size of
  621.       4 : Val(S, SINGLE(Float), Err);
  622.       8 : Val(S, DOUBLE(Float), Err);
  623.     end;
  624.  
  625.     StrToFloat := (Err = 0);
  626.   end;
  627.  
  628.  
  629. {--- String Routines ---}
  630.  
  631. Function StringToStr(var Str;
  632.                          Size : Byte): String;
  633.  
  634.   var
  635.     S : String;
  636.  
  637.   begin
  638.     if (Size > 255) then
  639.       Size := 255;
  640.  
  641.     Move(CHARS(Str), S[1], Size);
  642.     BYTE(S[0])  := Size;
  643.     StringToStr := S;
  644.   end;
  645.  
  646. Procedure StrToString(    S : String;
  647.                       var Str);
  648.  
  649.   begin
  650.     Move(S[1], Str, Length(S));
  651.   end;
  652.  
  653.  
  654.  
  655. {--- Decimal Routines ---}
  656.  
  657. Function DecimalToStr(var Decimal;
  658.                           Size : Byte): String;
  659.  
  660.   var
  661.     D     : Bytes Absolute Decimal;
  662.     Sign  : Char;
  663.     i     : Byte;
  664.     S     : String;
  665.  
  666.   begin
  667.     { extract sign }
  668.     if ((D[Size] AND $0F) = $0D) then
  669.       Sign := '-'
  670.     else
  671.       Sign := ' ';
  672.  
  673.     i := 1;
  674.     S := '';
  675.  
  676.     While (i < Size) do
  677.     begin
  678.       { high nibble Digit }
  679.       S := S + Chr(((D[i] AND $F0) Shr 4) + 48);
  680.       { low nibble Digit  }
  681.       S := S + Chr((D[i] AND $0F) + 48);
  682.       Inc(i);
  683.     end;
  684.  
  685.     { sign nibble }
  686.     S := S + Chr(((D[Size] AND $F0) Shr 4) + 48);
  687.  
  688.     { trim leading zeros }
  689.     i := 0;
  690.  
  691.     While (i < Length(S)) and (S[i + 1] = '0') do
  692.       Inc(i);
  693.  
  694.     if (i > 1) then
  695.     begin
  696.       Move(S[i + 1], S[1], Length(S) - i);
  697.       BYTE(S[0]) := Length(S) - i;
  698.     end;
  699.  
  700.     if (S = '') then
  701.       S := '0';
  702.  
  703.     if (S <> '0') and (Sign <> ' ') then
  704.       S := Sign + S;
  705.  
  706.     DecimalToStr := S;
  707.   end;
  708.  
  709. Function StrToDecimal(    S    : String;
  710.                       var Decimal;
  711.                           Size : Byte): Boolean;
  712.  
  713.   var
  714.     D : Bytes Absolute Decimal;
  715.     i : Byte;
  716.     j : Byte;
  717.     Err : Boolean;
  718.  
  719.   Procedure NextDigit(Shift : Boolean);
  720.     begin
  721.       if (S[j] >= '0') and (S[j] <= '9') then
  722.       begin
  723.         if Shift then
  724.           D[i] := D[i] OR ((BYTE(S[j]) - 48) Shl 4)
  725.         else
  726.           D[i] := D[i] OR (BYTE(S[j]) - 48);
  727.       end
  728.  
  729.       else if (S[j] <> DecimalPt) then
  730.       begin
  731.         Err := True;
  732.       end;
  733.     end;
  734.  
  735.   begin
  736.     FillChar(Decimal, Size, 0);
  737.     Err := False;
  738.  
  739.     if (S[1] = '-') then
  740.     begin
  741.       D[Size] := $0D;
  742.       Delete(S, 1, 1);
  743.     end
  744.  
  745.     else
  746.     begin
  747.       D[Size] := $0C;
  748.     end;
  749.  
  750.     j := Length(S);
  751.     i := Size;
  752.     NextDigit(True);
  753.     Dec(j);
  754.     Dec(i);
  755.  
  756.     While (i > 0) and (j > 0) do
  757.     begin
  758.       NextDigit(False);
  759.       Dec(j);
  760.  
  761.       if (j > 0) then
  762.       begin
  763.         NextDigit(True);
  764.         Dec(j);
  765.       end;
  766.  
  767.       Dec(i);
  768.     end;
  769.  
  770.     StrToDecimal := Err;
  771.   end;
  772.  
  773.  
  774.  
  775. {--- Numeric Routines ---}
  776.  
  777. Function NumericToStr(var Numeric;
  778.                           Size : Byte): String;
  779.  
  780.   var
  781.     S    : String;
  782.  
  783.   begin
  784.     Move(Numeric, S[1], Size);
  785.     BYTE(S[0]) := Size;
  786.  
  787.     Case S[Size] of
  788.       'J'..'R', '}' : S := '-' + S;
  789.     end;
  790.  
  791.     Case S[Length(S)] of
  792.       'A','J' : S[Size] := '1';
  793.       'B','K' : S[Size] := '2';
  794.       'C','L' : S[Size] := '3';
  795.       'D','M' : S[Size] := '4';
  796.       'E','N' : S[Size] := '5';
  797.       'F','O' : S[Size] := '6';
  798.       'G','P' : S[Size] := '7';
  799.       'H','Q' : S[Size] := '8';
  800.       'I','R' : S[Size] := '9';
  801.       '{','}' : S[Size] := '0';
  802.     end;
  803.  
  804.     NumericToStr := S;
  805.   end;
  806.  
  807. Procedure StrToNumeric(    S    : String;
  808.                        var Numeric;
  809.                            Size : Byte);
  810.  
  811.   var
  812.     i : Byte;
  813.  
  814.   begin
  815.     Case S[1] of
  816.       '-' :
  817.         begin
  818.           Delete(S, 1,1);
  819.  
  820.           Case S[Length(S)] of
  821.             '1' : S[Length(S)] := 'J';
  822.             '2' : S[Length(S)] := 'K';
  823.             '3' : S[Length(S)] := 'L';
  824.             '4' : S[Length(S)] := 'M';
  825.             '5' : S[Length(S)] := 'N';
  826.             '6' : S[Length(S)] := 'O';
  827.             '7' : S[Length(S)] := 'P';
  828.             '8' : S[Length(S)] := 'Q';
  829.             '9' : S[Length(S)] := 'R';
  830.             '0' : S[Length(S)] := '}';
  831.           end;
  832.         end;
  833.  
  834.       '+' :
  835.         begin
  836.           Delete(S, 1,1);
  837.  
  838.           Case S[Length(S)] of
  839.             '1' : S[Length(S)] := 'A';
  840.             '2' : S[Length(S)] := 'B';
  841.             '3' : S[Length(S)] := 'C';
  842.             '4' : S[Length(S)] := 'D';
  843.             '5' : S[Length(S)] := 'E';
  844.             '6' : S[Length(S)] := 'F';
  845.             '7' : S[Length(S)] := 'G';
  846.             '8' : S[Length(S)] := 'H';
  847.             '9' : S[Length(S)] := 'I';
  848.             '0' : S[Length(S)] := '{';
  849.           end;
  850.         end;
  851.     end;
  852.  
  853.     if (Length(S) < Size) then
  854.     begin
  855.       for i := 1 to Size - Length(S) do
  856.         Insert('0', S, 1);
  857.     end;
  858.  
  859.     Move(S[1], Numeric, Length(S));
  860.   end;
  861.  
  862.  
  863. Function LogicalToStr(var Logical;
  864.                           Size  : Byte): String;
  865.  
  866.   var
  867.     B : Byte Absolute Logical;
  868.     W : Word Absolute Logical;
  869.  
  870.   begin
  871.     if (Size = 1) then
  872.     begin
  873.       if (B = 0) then
  874.         LogicalToStr := 'FALSE'
  875.       else
  876.         LogicalToStr := 'TRUE '
  877.     end
  878.  
  879.     else if (Size = 2) then
  880.     begin
  881.       if (W = 0) then
  882.         LogicalToStr := 'FALSE'
  883.       else
  884.         LogicalToStr := 'TRUE '
  885.     end
  886.  
  887.     else
  888.     begin
  889.       LogicalToStr := 'ERROR';
  890.     end;
  891.   end;
  892.  
  893.  
  894. END.